home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc™ Source Code / Storage / Bento / CM / TOCObjs.h < prev    next >
Encoding:
Text File  |  1996-08-28  |  21.9 KB  |  439 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:         TOCObjs.h  
  3.  
  4.     Contains:    Container Manager TOC Objects Interfaces
  5.  
  6.     Written by:    Ira L. Ruben
  7.  
  8.     Owned by:    Ed Lai
  9.  
  10.     Copyright:    © 1991 - 1996 by Apple Computer, Inc., all rights reserved.
  11.  
  12.     Change History (most recent first):
  13.  
  14.          <2>     1/15/96    TJ        Cleaned Up
  15.          <2>     8/26/94    EL        #1182275 Add constants EditedRecently and
  16.                                     DeletedRecently to be used for merging.
  17.          <2>     3/31/94    EL        Add cmPutObjectInTOC call. #1150214
  18.          <1>      2/3/94    EL        first checked in
  19.          <4>      2/2/94    EL        cmFreeLastDeletedObject no longer needed,
  20.                                                     use refNumHandling to control freeing.
  21.          <3>    10/29/93    EL        Add new call cmFreeLastDeletedObject so we
  22.                                                     can free the reference associated with
  23.                                                     value
  24.          <2>     10/4/93    EL        Add cmGetMasterListTail call.
  25.  
  26.     To Do:
  27. */
  28.  
  29. /*---------------------------------------------------------------------------*
  30.  |                                                                           |
  31.  |                           <<<  TOCObjs.h   >>>                            |
  32.  |                                                                           |
  33.  |                  Container Manager TOC Objects Interfaces                 |
  34.  |                                                                           |
  35.  |                               Ira L. Ruben                                |
  36.  |                                 11/20/91                                  |
  37.  |                                                                           |
  38.  |                  Copyright Apple Computer, Inc. 1991-1994                 |
  39.  |                           All rights reserved.                            |
  40.  |                                                                           |
  41.  *---------------------------------------------------------------------------*
  42.  
  43.  All TOC object manipulation routines are contained in this file. Only manipulations down
  44.  to the object level are done here.  The objects themselves contain pointers off to lower
  45.  level structures which are maintained by TOCEntries.c. The split is done this way to keep
  46.  the accessing of objects separate from the stuff represented by those objects.
  47.  
  48.  TOC objects are based on their ID's.  The ID's do not lend themselves well to the 
  49.  standard binary-tree mechanism we use elsewhere so another scheme is used here.
  50.  
  51.  TOC objects are access through a set of index tables.  The tables correspond to "powers"
  52.  of a chosen index table size.  For example, if the size was 100 and we had ID 1234567 we
  53.  would have 4 indices: 01, 23, 45, 67.  Four index tables would exist each corresponding
  54.  to the indices 00 to 99.  The first table would have its 01'th entry pointing to the next
  55.  table.  That next table would have its 23rd entry pointing to the third table.  The 
  56.  third table would have its 45th entry pointing to the last table.  The 67th entry in the
  57.  last table would point to the actual object with ID 1234567.
  58.  
  59.  The actual number of tables is dependent on the table size and the max ID value supported
  60.  (which is 0xFFFFFFFF).  Small ids are padded with 00 as the higher order indices.
  61.  
  62.  The number of tables is dependent on the table size and the sparseness of the ID's
  63.  presented.  This scheme represents a comprimise between speed, space, and the fact that
  64.  we want to always have the ID's in sorted order.  We get the sorted order by walking the
  65.  index tables in the appropriate way.
  66.  
  67.  The support for this scheme has been generalized to allow any size index table. 
  68.  
  69.  Multiple TOC's are supported.  Each TOC is tied to a anonymous reference number from
  70.  the outside caller's point of view.  In here it is a pointer to a control block that
  71.  contains the root pointer to the TOC index tables and the control variables to access
  72.  through the index tables mentioned above.
  73.  
  74.  Each TOC is independent.  Since the control variables are tied to the TOC, it is allowed
  75.  to have different size index tables for different TOC.  It's not clear this has any
  76.  benefit, but it's allowed.
  77.  
  78.  The TOC routines only know the final TOC entries down to the level of "objects".  The
  79.  objects themselves contain fields maintained by other routines outside the scope of this
  80.  file.  In particular the object is mainly a "head cell" for a list of entries chained
  81.  off of it.  The  ListMgr package is used to maintain the lists by the caller by using the
  82.  object.  Other fields are provided as well which are also maintained by the caller.  The
  83.  only exception is the object ID number which is known to this file.
  84. */
  85.  
  86. #ifndef __TOCOBJECTS__
  87. #define __TOCOBJECTS__
  88.  
  89.  
  90. #include <setjmp.h>
  91.  
  92. /*------------------------------------------------------------------------------------*
  93.  | W A R N I N G - - -> this header as well as  TOCObjs.h   and  TOCEnts.h   all have |
  94.  |                      mutual references.  The include order is NOT arbitrary.  It's |
  95.  |                      the only one that works!  Even with it we have to do some     |
  96.  |                      forward struct pointer references of the form "struct foo *p" |
  97.  *------------------------------------------------------------------------------------*/
  98.  
  99. #ifndef __CMTYPES__
  100. #include "CMTypes.h"
  101. #endif
  102. #ifndef __CM_API_TYPES__
  103. #include "CMAPITyp.h"
  104. #endif
  105. #ifndef __CONTAINEROPS__
  106. #include "Containr.h"  
  107. #endif
  108. #ifndef __LISTMGR__
  109. #include "ListMgr.h"
  110. #endif
  111.  
  112. struct Container;
  113. struct TOCObject;
  114.  
  115.                                                                     CM_CFUNCTIONS
  116.  
  117.  
  118. /* All in-memory objects have the following layout. There objects are accessed by their    */
  119. /* object ID.                                                                                                                                                     */
  120.  
  121. struct TOCObject {                                        /* Layout of a TOC object:                                                */
  122.     CMObjectID             objectID;                    /*        the object's ID     (keep first for debugging) */
  123.     ListHdr                     propertyList;            /*         list of object property entries                            */
  124.     struct Container *container;                /*        ptr to "owning" container control block            */
  125.     struct TOCObject *nextObject;                /*         chain to next object by increasing ID                */
  126.     struct TOCObject *prevObject;                /*         chain to previous object by decreasing ID        */
  127.     struct TOCObject *nextTypeProperty;    /*         chain of next type/property by increasing ID*/
  128.     struct TOCObject *prevTypeProperty;    /*         chain of previous type/property by decr. ID    */
  129.     CM_USHORT                  objectFlags;                /*        info flags about the object                                    */
  130.     CMRefCon                  objectRefCon;            /*        user's object refCon                                                */
  131.     CM_ULONG               useCount;                    /*        count of nbr of times "used"                                */
  132.     struct TOCObject *nextTouchedObject;/*        link to next touched object                                    */
  133.     ListHdr                     touchedList;                /*         values/properties touched IN this object        */
  134. };
  135. typedef struct TOCObject TOCObject, *TOCObjectPtr;
  136.  
  137. /* NOTE: there is a mutual reference here between Container and TOCObject.  They refer    */
  138. /* to each other!  Thus we must do the weird "struct Container" to define the container    */
  139. /* pointer above.  Sorry about that!                                                                                                        */
  140.  
  141. #define UndefinedObject         0x0001U        /* objectFlags: 1 ==> object created but undefined*/
  142. #define ObjectObject                 0x0002U        /*                                 ==> object is a base object            */
  143. #define PropertyObject             0x0004U        /*                                ==> object is a property                */
  144. #define TypeObject                     0x0008U        /*                               ==> object is a type                        */
  145. #define DeletedObject                0x0010U        /*                                 ==> object has been deleted            */
  146. #define DeletedRecently            0x0200U        /*                                ==> object prop deleted recently*/
  147. #define EditedRecently            0x0400U        /*                                ==> object edited recently            */
  148. #define DynamicValuesObject    0x0800U        /*                                ==> object "owns" dynamic values*/
  149. #define TouchedObject                0x1000U        /*                                ==> object has been "touched"        */
  150. #define ProtectedObject            0x2000U        /*                                ==> object is locked/protected    */
  151. #define LinkedObject                0x4000U        /*                                ==> object linked to master lsts*/
  152. #define UndefObjectCounted     0x8000U        /*                                ==> object counted as undefined    */
  153.  
  154. #define DefaultIndexTableSize    256            /* "recommended" index table size                                    */
  155. #define MinIndexTableSize            16            /* minimum index table size                                                */
  156. #define MaxIndexTableSize            1024        /* maximum index table size                                                */
  157.  
  158. #define ALLOBJECTS            0x0000000UL        /* starting ID for cmForEachObject() for all objs    */
  159. #define MAXUSERID                0xFFFFFFFFUL    /* ending ID to scan objects to the highes user ID*/
  160.  
  161. /* The following is used to increment object ID counters. The counter is set to 0 if it    */
  162. /* wraps.  Any attempt to use the counter after that to define an object will result in    */
  163. /* an error.                                                                                                                                                        */
  164.  
  165. #define IncrementObjectID(id) (id = ((id) == MAXUSERID) ? 0x00000000UL : ++(id))
  166.  
  167.  
  168. void *cmCreateTOC(CM_ULONG tableSize, const struct Container *container);
  169.     /*
  170.     This routine MUST be called before any other TOC routine is called. It is used to set up
  171.     the data needed by the other TOC routines.  A "reference number" is returned to the
  172.     caller who must pass it to ALL the other TOC routines.  Any number of TOC can be 
  173.     created.  By passing the returned "reference number" to the other routines they will
  174.     operate on the corresponding TOC.
  175.  
  176.     Note, a TOC is "owned" by a container in the sense that each TOC is associated with a
  177.     particular container.  Container "objects" need to be able to get back at the container
  178.     control block that is associated with the TOC containing the object.  Thus the container
  179.     control block is passed here so that we may save it and store it into all created 
  180.     objects.
  181.     
  182.     Internally, i.e., in this file, the "reference number" is actually a pointer to a control
  183.     block containing the root pointer to the TOC index tables (set to NULL here) and the set
  184.     of variables needed to convert an object ID value into a set of indices which are used
  185.     to index into the index tables that lead to the actual TOC object corresponding to the
  186.     ID.  There is also a use count.  The use count is explained in cmUseTOC().
  187.     
  188.     The single parameter is the index table size.  See TOC.c on exactly how this is used.
  189.     But for purposes of description here, the tableSize determines how many index tables
  190.     we indirect through to get at an object and the size of each table (each entry in a
  191.     table is a pointer).  There is a trade-off between space and time here.  So that's why
  192.     the tableSize is a parameter.
  193.     
  194.     This function returns the pointer if we can allocate the control block. NULL is returned
  195.     if the allocation fails.
  196.     */
  197.  
  198.  
  199. void *cmUseTOC(void *toc, struct Container *container);
  200.     /*
  201.     This allows multiple users of the same TOC for the specified container.  This can come
  202.     about due to updating containers which want to use the TOC of their target.  They call
  203.     this routine to register the additional use of the specified TOC.  It is returned as the
  204.     function result but with the owning container of the TOC changed to the one specified.
  205.     Here we register the additional use by incrementing a use count of the TOC.  When
  206.     cmDestroyTOC() is called to remove the TOC it will decrement the use count.  Only when 
  207.     the count goes to 0 is the TOC actually destroyed.
  208.     
  209.     Since the owning container of the TOC is being changed, it is assumed the caller knows
  210.     what s/he is doing!  In particular we only do this for a container updating a target
  211.     and after the updates are applied, we want to use the target's TOC, but associate it with
  212.     the updating container.  This will allow new updates to be recorded in the updating
  213.     container, but in a TOC common to both the updater and the target.
  214.     */
  215.  
  216.  
  217. TOCObjectPtr cmCreateObject(const void *toc, const CMObjectID objectID, 
  218.                                                         CM_USHORT objectFlags, CMBoolean *dup);
  219.     /*
  220.     This routine is called to create a new object in the specified TOC for the specified ID.
  221.     A "raw" object is created and the function returns a pointer to where it was placed in
  222.     the TOC. If there is already an object with that ID the TOC, a pointer to it is returned
  223.     and dup set to true. The function returns NULL if there is an allocation failure so that
  224.     we couldn't create the object.
  225.     
  226.     Note that the object created is "raw" in the sense that all info in it is NULLed out.
  227.     This is the lowest level routine whose sole goal in life is object creation.  The caller 
  228.     is responsible for maintaining the objects.  Life is simpler this way (not to mention
  229.     more maintainable)!
  230.     */
  231.  
  232.  
  233. void cmUncreateObject(const void *toc, const CMObjectID id, CMRefCon refCon,
  234.                                           void (*freeAction)(TOCObjectPtr object, CMRefCon refCon));
  235.     /*
  236.     This routine is the inverse (more-or-less) of cmCreateObject().  It removes an object
  237.     with the specified ID from the specified TOC.  The space for the object is freed.  The
  238.     lowest level index table entry pointing to the object is made NULL to indicate it is
  239.     undefined.  However, the higher level tables leading to the lowest table are not changed.
  240.     This doesn't hurt except to take up space if the object being deleted is the only one in
  241.     the tables leading to it.  But it's not worth all the extra work!
  242.     
  243.     As discussed in cmCreateObject() we simply create a "raw" object and return.  The caller
  244.     builds upon the object with lower level link structures. Unfortunately here, we have to 
  245.     allow the caller to handle his or her stuff BEFORE we delete the object.  Thus a
  246.     freeAction routine may be passed which is called prior to the freeing of the object. A
  247.     "refCon" is also provided which the caller can use as a communication facility to convey
  248.     additional info to the freeAction routine.
  249.  
  250.   Note, the freeAction may be passed as NULL, in which case only the object is deleted and
  251.   it is assumed averything linked to it must have already been deleted.
  252.     */
  253.  
  254.  
  255.  
  256. void cmDelete1Object(const void *toc, const CMObjectID id, CMRefCon refCon,
  257.                                        void (*deleteAction)(TOCObjectPtr object, CMRefCon refCon));
  258.     /*
  259.     This routine is the inverse (more-or-less) of cmCreateObject().  It removes an object
  260.     with the specified ID from the the specified TOC.  Unlike cmUncreateObject() however,
  261.     the space for the object is NOT freed.  Rather the object is RELINKED on to a singly
  262.     linked list of deleted objects pointed to by deletedObjects (a global).  This is done
  263.     to prevent dangling pointers that the API user may have as object "refNum"s (we give 
  264.     the API user these pointers as CMObject's).
  265.     
  266.     Since the object is removed from the TOC it will never be seen by us here using the TOC
  267.     index tables.  Just as in cmUncreateObject() the lowest level index table entry pointing
  268.     to the object is made NULL to indicate it is undefined in the TOC.
  269.     
  270.     Also as in cmUncreateObject() we allow the caller to do something with the object before
  271.     it is deleted from the TOC and before we link it on to the deletedObjects list.  The
  272.     calling conventions are the same and NULL may be passed to indicate no action is to be
  273.     performed.
  274.     
  275.     Caution: the deletedObjects list utilizes the nextObject field of an object to link its
  276.     objects.  That field is also a link field for active objects.  Thus the object must be
  277.     unlinked from the active object chain BEFORE calling this routine. 
  278.     */
  279.     
  280.  
  281. TOCObjectPtr cmFindObject(const void *toc, const CMObjectID id);
  282.     /*
  283.      Given an object ID in a TOC, this function returns a pointer to the corrsponding object
  284.      or NULL if the object does not exist.
  285.     */
  286.  
  287.  
  288. int cmForEachObject(const void *toc, CMObjectID startingID, CMObjectID endingID, 
  289.                                       CMRefCon refCon, void (*action)(TOCObjectPtr object, CMRefCon refCon));
  290.     /*
  291.     Do (call) the specified action for each object in the specified TOC with object ID's
  292.     greater than or equal to the startingID and less than or equal to endingID.  The pointer
  293.     to each TOC object is passed to the action routine along with a "refCon" which the caller
  294.     can use as a communication facility to convey additional info to the action routine.  0
  295.     is returned to indicate successful completion.  Use the AbortForEachObject(x) (a macro)
  296.     in the action routine to abort the interator.  The "x" should be a positive integer which
  297.     is returned from cmForEachObject() and it should not be 0.
  298.     */
  299.  
  300.  
  301. #define AbortForEachObject(x) longjmp(SESSION->cmForEachObjectEnv, x)
  302.     /*
  303.     Use this in routines passed to cmForEachObject() to abort the interator. The value of x
  304.     is returned from cmForEachObject(). It should be positive and nonzero, since 0 is the
  305.     "success" return value for cmForEachObject(). It is assumed that the variable "container"
  306.     is the current container pointer.
  307.     */
  308.  
  309.  
  310. void cmDestroyTOC(void **toc, CMRefCon refCon,  CMBoolean objectToo,
  311.                                     void (*deleteAction)(TOCObjectPtr object, CMRefCon refCon));
  312.     /*
  313.     This routine is called to remove wipe a TOC out of existence.  All existing objects in
  314.     the TOC, supporting index tables, and deleted objects on the deletedObjects list are
  315.     freed.  The "reference number" must not be used beyond this point.  The TOC pointer is
  316.     NULLed out prior to return to prevent further use.
  317.     
  318.     Note, that anything "below" an object entry is NOT handled here, i.e., all stuff that 
  319.     the object might be pointing to.  The caller MUST provide a way of deleting that stuff.
  320.     To this end, the caller should provide a "deleteAction" routine.  It is called just
  321.     prior to deleting each object.  The pointer to each object is passed to the deleteAction
  322.     routine along with a "refCon" which the caller can use as a communication facility to
  323.     convey additional info to the deleteAction routine.
  324.     
  325.     The objectToo flag permits you to destroy the toc without deleting the objects.
  326.  
  327.     The deleteAction value may be passed as NULL.  If that is the case, then (obviously) no
  328.     call is done and the object is simply deleted.  It's not clear anyone will do such a
  329.     thing, but it's provided anyway!
  330.     
  331.     Since multiple users of the same TOC are permitted (because of updating), a use count is
  332.     maintained of the number of users of the TOC.  Additional users call cmUseTOC() to 
  333.     increment the useCount.  It is decremented here.  Only when the count goes to 0 do is
  334.     the TOC actually destroyed.
  335.     */
  336.  
  337.  
  338. TOCObjectPtr cmLinkObject(const void *toc, TOCObjectPtr theObject, 
  339.                                                     TOCObjectPtr afterThisObject);
  340.     /*
  341.     This routine is (doubly) links an object (theObject) into the master object chains whose
  342.     head and tail pointers are contained in the specified TOC.  The objects is inserted in
  343.     the object chain following afterThisObject. If afterThisObject is NULL the object is
  344.     appended to the end of its list(s).  The function returns the input object pointer as its
  345.     result.
  346.     
  347.     There are three master chains:
  348.     
  349.          (1).  A chain of property objects.
  350.          (2).  A chain of type objects.
  351.          (3).  A chain of ALL objects no matter what their type.  It may be neither a type or
  352.                      property.
  353.                      
  354.     Chain (3) is always built. The decision on whether to do (1) or (2) is a function of the
  355.     objectFlags field contained in the object itself.  So the caller must have set these
  356.     prior to calling this routine.
  357.     */
  358.     
  359.  
  360. TOCObjectPtr cmUnlinkObject(const void *toc, TOCObjectPtr theObject);
  361.     /*
  362.   This routine is the inverse to cmLinkObject().  It unlinks the specified object from the
  363.   master object chains whose head and tail pointers are contained in the specified TOC.
  364.   The function returns the input object pointer as its result.
  365.     
  366.     The object is always deleted from the chain of all objects.  It is also deleted from the
  367.     property or type chain if the objectFlags field contained in the object itself indicates
  368.     it is a property or type (see cmLinkObject() above for further details about the chains).
  369.     */
  370.  
  371.  
  372. TOCObjectPtr cmGetMasterListHead(const void *toc, CM_USHORT objectKindFlag);
  373.     /*
  374.     This routine returns the head of one of the master chain lists in a TOC depending on 
  375.     the objectKindFlag.  This flag should be one of the standard object flags; ObjectObject,
  376.     PropertyObject, or TypeObject.  The respective chain head will be returned as the function
  377.     result.
  378.     
  379.     These chain heads are used by the CMGetNextObject(), CMGetNextProperty(), and
  380.     CMGetNextType() routines to start them off.
  381.     */
  382.  
  383. TOCObjectPtr cmGetMasterListTail(const void *toc, CM_USHORT objectKindFlag);
  384.     /*
  385.     This routine returns the tail of one of the master chain lists in a TOC depending on 
  386.     the objectKindFlag.  This flag should be one of the standard object flags; ObjectObject,
  387.     PropertyObject, or TypeObject.  The respective chain head will be returned as the function
  388.     result.
  389.     
  390.     These chain tails are used by the CMGetPrevObject(), CMGetPrevProperty(), and
  391.     CMGetPrevType() routines to start them off.
  392.     */
  393.  
  394. void cmChangeRefNumHandling(const void *toc, CMBoolean setting);
  395.     /*
  396.     Normally all deleted values and objects are "remembered".  A value's header is placed on
  397.     the deleted values list attacthed to the container control block.  Deleted TOCObject's
  398.     are placed on the deleted object list attached to the toc control block.  Both value
  399.     headers and TOCObject's are the refNums we give to the user.  By remembering these we
  400.     can check for attempted reuse and report an error.
  401.     
  402.     However, there are times we don't want to track these things because we know internally
  403.     what we're doing.  So an override switch is provided.  Since
  404.     both kinds of refNums are TOC entities, the override is on a TOC basis and hence the
  405.     switch attached to the TOC control block.
  406.     
  407.     This routine is therefore provided to change the setting the override switch.  It is a
  408.     boolean with true meaning that deleted refNums are to be saved on their respective lists.
  409.     Setting the switch to false will cause the refNum to simply be freed.
  410.     
  411.     By calling cmKeepDeletedRefNums(), the current setting of the switch can be interrogated
  412.     to decide what to do.
  413.  
  414.   Oh, in case you're curious, one case where we suppress the refNum tracking is when we are
  415.   applying updates at open time where updating instructions are being interpreted to 
  416.   update a target container.
  417.     */
  418.  
  419.  
  420. CMBoolean cmKeepDeletedRefNums(const void *toc);
  421.     /*
  422.     As described above, this is used by all outside callers to see if a refNum is to be saved
  423.     on its deleted list.  The only thing outside callers can possibly be interested in is
  424.     for deleted values and whether the value headers are to be saved on the deleted values
  425.     list.
  426.     */
  427.     
  428. void cmPutObjectInTOC(const void *toc, TOCObjectPtr object, TOCObjectPtr *replacedObject);
  429.     /*
  430.     This routine let put put an object (currently belonging to another TOC) and put it into
  431.     this TOC. If an object of the same ID is already in this TOC, that old object in this
  432.     TOC will be replaced and also returned from the routine so that the caller can deal
  433.     with it.
  434.     
  435.     This routine is used to move objects from one TOC to another.
  436.     */        
  437.                                                           CM_END_CFUNCTIONS
  438. #endif
  439.